import CustomEventClass.JDateEvent;
import CustomEventClass.JDateEventListener;
import java.awt.event.*;
import java.io.File;

import jxl.*;
import jxl.write.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableModel;

//Controller class should update both model and view component.
//Update are done by calling the method. This class doesn't contain any code to update neither model nor view
public class MoneyKeeperController {
	private MoneyKeeperModel model;
	private MoneyKeeperView view;
	private String ID;
	private ListModifier listModifier;
	
	MoneyKeeperController(MoneyKeeperModel model, MoneyKeeperView view){
		this.model = model;
		this.view = view;
		view.addJDateEventListenerInView(new DTListener());
		view.addSubmitListenerInView(new SubmitListener());
		view.addResetListenerInView(new ResetListener());
		view.addDeleteListener(new DeleteListener());
		view.addExcelListener(new ExcelExportListener());
		view.addDeleteAllListener(new DeleteAllListener());
		view.addModifyListener(new ModifyListener());		
		view.addClearMemoListener(new ClearMemoListener());
		view.addSaveMemoListener(new SaveMemoListener());
		view.addLoadMemoListener(new LoadMemoListener());	
		view.addEditExpenseListListener(new EditExpenseListListener());
		view.addEditIncomeListListener(new EditIncomeListListener());
		view.addEditUserListListener(new EditUserListListener());
		view.addEditTransMethodListListener(new EditTransMethodListListener());
		view.addAboutListener(new AboutMenuListener());
		view.addHelpListener(new HelpMenuListener());
		view.addCallEditScreenListener(new EditScreenListener());
		view.addCallSummaryScreenListener(new SummaryScreenListener());
	}
		
	
	private class DTListener implements JDateEventListener{
		public void dateEventHandler(JDateEvent ev) {
			view.entryForm.setDateText(view.dtPanel.getDate());
			model.setQueryDate(view.dtPanel.getCalendarVar());
			if (ev.getPageType().equals(JDateEvent.MONTH)){
				model.getMonthData();
				model.getDailyIncomeData();
				model.getDailyExpenseData();
				
			}else if (ev.getPageType().equals(JDateEvent.DAY)){
				model.getDailyIncomeData();
				model.getDailyExpenseData();
				
			}
			view.setMemo(model.loadMemo(model.getYrMonth()));
		}				
	}
	
	private class SubmitListener implements ActionListener{
		public void actionPerformed(ActionEvent submitClicked) {
			
			try{
				if (view.entryForm.getTransContent().equals(null) || view.entryForm.getTransContent().equals(new String())){
					throw new ValueCannotBeEmptyException();
				}				
				float amount = Float.parseFloat((view.entryForm.getAmount()));
				
				if(view.entryForm.getSubmitButtonText().equals(new String("SUBMIT"))){
					model.insertData(view.entryForm.getDateText(), 
						view.entryForm.getTransCategory(), view.entryForm.getTransContent(), view.entryForm.isIncomeSelected(), view.entryForm.getUser(), 
						view.entryForm.getTransMethod(), view.entryForm.getAmount());
				}else{
					model.modifytData(ID, view.entryForm.getUser(), view.entryForm.getDateText(), view.entryForm.getTransCategory(), view.entryForm.getTransContent(),
							view.entryForm.isIncomeSelected(), view.entryForm.getTransMethod(), view.entryForm.getAmount());
				}
				
			}catch(ValueCannotBeEmptyException e){
				view.showMessage(e.getMessage());
				
			}catch(NumberFormatException e){
				view.showMessage("Please enter numeric values\n" + "in the amount field.");
				view.entryForm.setAmountText(null);			
			}finally{
				tableRefresh();
				new ResetListener().actionPerformed(null);
			}			
		}
	}
	
	private class ResetListener implements ActionListener{
		public void actionPerformed(ActionEvent resetClicked) {
			view.entryForm.setTransContent("");
			view.entryForm.setAmountText("");
			view.entryForm.setSubmitButtonText("SUBMIT");
			view.entryForm.setDateText(view.dtPanel.getDate());
			view.updateAllLists();
		}		
	}
	
	private class ExcelExportListener implements ActionListener{
		public void actionPerformed(ActionEvent excelClicked) {
			try {
					JFileChooser fc = new JFileChooser();
					File file;
					
					fc.addChoosableFileFilter(new FileNameExtensionFilter("Excel File", "xls","xlsx"));
					int returnVal = fc.showSaveDialog(view);
					
					if (returnVal == JFileChooser.APPROVE_OPTION) {
						if(fc.getSelectedFile().toString().lastIndexOf('.')==-1){
							file = new File(fc.getSelectedFile()+".xls");
						}else{
							file = fc.getSelectedFile();
						}
		                
		                
			            WritableWorkbook workbook = Workbook.createWorkbook(file);
			            WritableSheet sheet = workbook.createSheet("First Sheet", 0); 
			            TableModel model = view.monthlyTable.dataTable.getModel();

			            for (int i = 2; i < model.getColumnCount(); i++) {
			                Label column = new Label(i-2, 0, model.getColumnName(i));
			                sheet.addCell(column);
			            }
			            int j = 0;
			            for (int i = 0; i < model.getRowCount(); i++) {
			                for (j = 2; j < model.getColumnCount(); j++) {
			                    Label row = new Label(j-2, i + 1, 
			                            model.getValueAt(i, j).toString());
			                    sheet.addCell(row);
			                }
			            }
			            workbook.write();
			            workbook.close();
						
		            } 

		        } catch (Exception ex) {
		            ex.printStackTrace();
		        }
			}	
	}
	
	private class DeleteListener implements ActionListener{
		public void actionPerformed(ActionEvent deleteClicked) {
			switch(view.monthlyTable.dataTable.getSelectedRowCount()){
				case 0:
					view.showMessage("Please select the data you wish to delete.");
					break;
				default:
					int selection = JOptionPane.showOptionDialog(view, "Delete Selected Item(s)?", "Delete Confirmation", 
							JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null,null);
					if(selection == 0){
						
						for (int i: view.monthlyTable.getSelectedRows()){
							
							
							ID = String.valueOf(view.monthlyTable.getValueAt(i, 0));

							
							model.delete(ID);
							
						}
						
						tableRefresh();
					}
					break;
				}
			
		}		
	}
	
	private  class DeleteAllListener implements ActionListener{
		public void actionPerformed(ActionEvent deleteAllClicked) {
			int selection = JOptionPane.showOptionDialog(view, "Delete All Item(s)?", "Delete All Confirmation", 
					JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null,null);
			if (selection == 0){
				model.setQueryDate(view.dtPanel.getCalendarVar());
				model.deleteAll();
				tableRefresh();
			}			
		}		
	}
	
	private class ModifyListener implements ActionListener{
		public void actionPerformed(ActionEvent modifyClicked) {
			
			switch(view.monthlyTable.dataTable.getSelectedRowCount()){
			case 0:
				view.showMessage("Please select the data you wish to modify.");
				break;
			case 1:
				view.entryForm.setSubmitButtonText("MODIFY");
				ID = String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 0));
				String user = String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 2));//
				String t_date = String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 3));
				String category =String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 4));//
				String transactions = String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 5));
				String trans_method = String.valueOf(view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 6));//
				String income = ""+view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 7);
				String expense = ""+view.monthlyTable.getValueAt(view.monthlyTable.dataTable.getSelectedRow(), 8);

				//Set Date
				view.entryForm.setDateText(t_date);
				//Set Transactions
				view.entryForm.setTransContent(transactions);
				
				
				
				//Set Radio Button
				if (income.equals(new String("0.0"))){
					view.entryForm.setAmountText(expense);
					view.entryForm.selectExpense();
					view.entryForm.setTransExpenseList(tempList(category,view.entryForm.getTransExpenseList()));
					//set Expense List
					
				}
				else{
					view.entryForm.setAmountText(income);
					view.entryForm.selectIncome();
					view.entryForm.setTransIncomeList(tempList(category,view.entryForm.getTransIncomeList()));
					//set Income List
				}
				view.entryForm.setTransactionMethodList(tempList(trans_method,view.entryForm.getTransactionMethodList()));
				
				view.entryForm.setUserList(tempList(user, view.entryForm.getUserList()));
						
				break;
			default:
				view.showMessage("You can modify one data at a time!");
				break;
			}
		}		
	}
	
	private class SaveMemoListener implements ActionListener{
		public void actionPerformed(ActionEvent saveMemoClicked) {
			model.saveMemo(view.getMemo());
			view.showMessage("Memo has been saved!");
		}
		
	}
	private class LoadMemoListener implements ActionListener{
		public void actionPerformed(ActionEvent loadMemoClicked) {
			view.setMemo(model.loadMemo(model.getYrMonth()));
			
		}
		
	}
	private class ClearMemoListener implements ActionListener{
		public void actionPerformed(ActionEvent clearMemoClicked) {
			view.clearMemo();					
		}		
	}

	private class ValueCannotBeEmptyException extends Exception{
		ValueCannotBeEmptyException(){
			super("Fields cannot be blank.");
		}
	}
	
	private class EditScreenListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			view.callEditScreen();			
		}
	}
	
	private class SummaryScreenListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			view.callSummaryScreen();			
		}
	}

	private class EditIncomeListListener implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			listModifier = new ListModifier(ListModifier.INCOME_LIST, model,view);
		}
	}
	
	private class EditExpenseListListener implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			listModifier = new ListModifier(ListModifier.EXPENSE_LIST, model,view);
		}
	}
	
	private class EditUserListListener implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			listModifier = new ListModifier(ListModifier.USER_LIST, model,view);
		}
	}
	
	private class EditTransMethodListListener implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			listModifier = new ListModifier(ListModifier.TRANS_METHOD_LIST, model,view);
			
		}
	}
	
	private class AboutMenuListener implements ActionListener{
		public void actionPerformed(ActionEvent ev) {
			JOptionPane.showMessageDialog(view,
				    "MoneyKeeper\n"+
				    "Version 1.0 - Developed by Kyungho Shawn Jung\n"+
				    "Found Bug? Contact tabris1103@hotmail.com",
				    "About MoneyKeeper",
				    JOptionPane.PLAIN_MESSAGE);
		}
		
	}
	
	private class HelpMenuListener implements ActionListener{
		public void actionPerformed(ActionEvent ev) {
			JOptionPane.showMessageDialog(view,
				    "Manual will be available in next update",
				    "Sorry, Manual is not ready yet...",
				    JOptionPane.PLAIN_MESSAGE);
		}
		
	}
	
	public void tableRefresh(){
		model.getMonthData();
		model.getDailyIncomeData();
		model.getDailyExpenseData();
	}
	
	private String[] tempList(String extraItem, String[] existingList){
		String[] returnList;
		boolean isIn = false;
		int index = 0;
		for(int i=0; i< existingList.length; i++){
			if(existingList[i].toUpperCase().equals(extraItem.toUpperCase())){
				isIn = true;
				index = i;
			}
		}
				
		if(isIn){
			returnList = new String[existingList.length];
			returnList = existingList;
			String temp = returnList[0];
			returnList[0] = existingList[index];
			existingList[index]= temp;
			
		
		}else{
			returnList = new String[existingList.length + 1];
			for(int i=0; i< existingList.length + 1; i++){
				if (i==0){
					returnList[i] = extraItem;				
				}else{
					returnList[i] = existingList[i-1];
				}				
			}
		}
		return returnList;
	}
	
}
	
